package filters

import (
	"api/types"
	"sync"
	"github.com/valyala/fasthttp"
)
func init(){
	//todo
	//从redis中获取各个路由都实际注册了什么filters
	//这样每次请求路由只会执行那些特定filters
	//NewFilterHandler().Register("abc",NewFilterAcl())
	//NewFilterHandler().Register("access_token",NewFilterRateLimit())
}
var (
	filterHandler *FilterHandler
	filterSync sync.Once
)
type Filter interface{
	Pre(ctx *types.ProxyContext,fasthttpCtx *fasthttp.RequestCtx)(bool,int,string)
	Post(ctx *types.ProxyContext,fasthttpCtx *fasthttp.RequestCtx)(bool,int,string)
}
func NewFilterHandler() *FilterHandler{
	filterSync.Do(func() {
		filterHandler = &FilterHandler{}
		filterHandler.filters = make(map[string][]Filter)
		filterHandler.allFilters = append(
			filterHandler.allFilters,
			//NewFilterAcl(),
			NewFilterJwt(),
			NewFilterRateLimit(),
			NewFilterInit(),
		)
	})
	return filterHandler
}
type FilterHandler struct{
	sync.Mutex
	filters map[string] []Filter
	allFilters []Filter
}
func (fh *FilterHandler) Register(mapkey string,filter Filter){
	fh.Lock()
	defer fh.Unlock()
	fh.filters[mapkey] = append(fh.filters[mapkey], filter)
	//log.Success("%s",fh)
}
// invoke all filters we have defaultly
// except request got it's specific filters,then we just invoke those
func (fh *FilterHandler) TriggerPreFilters(ctx *types.ProxyContext,fasthttpCtx *fasthttp.RequestCtx) (bool,int,string){
	if _,ok := fh.filters[ctx.Mapkey];ok{
		for _,filter := range fh.filters[ctx.Mapkey]{
			if flag,code,msg := filter.Pre(ctx,fasthttpCtx);!flag{
				return flag,code,msg
			}
		}
	}else{
		for _,filter := range fh.allFilters{
			if flag,code,msg := filter.Pre(ctx,fasthttpCtx);!flag{
				return flag,code,msg
			}
		}
	}
	return true,0,""
}

func (fh *FilterHandler) TriggerPostFilters(ctx *types.ProxyContext,fasthttpCtx *fasthttp.RequestCtx) (bool,int,string){
	if _,ok := fh.filters[ctx.Mapkey];ok{
		for _,filter := range fh.filters[ctx.Mapkey]{
			if flag,code,msg := filter.Post(ctx,fasthttpCtx);!flag{
				return flag,code,msg
			}
		}
	}else{
		for _,filter := range fh.allFilters{
			if flag,code,msg := filter.Post(ctx,fasthttpCtx);!flag{
				return flag,code,msg
			}
		}
	}
	return true,0,""
}